package course.examples.compass;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;
import android.widget.RelativeLayout;
public class CompassActivity extends Activity implements SensorEventListener {
@SuppressWarnings("unused")
private String TAG = "SensorCompass";
// Main View
private RelativeLayout mFrame;
// Sensors & SensorManager
private Sensor accelerometer;
private Sensor magnetometer;
private SensorManager mSensorManager;
// Storage for Sensor readings
private float[] mGravity = null;
private float[] mGeomagnetic = null;
// Rotation around the Z axis
private double mRotationInDegress;
// View showing the compass arrow
private CompassArrowView mCompassArrow;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFrame = (RelativeLayout) findViewById(R.id.frame);
mCompassArrow = new CompassArrowView(getApplicationContext());
mFrame.addView(mCompassArrow);
// Get a reference to the SensorManager
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
// Get a reference to the accelerometer
accelerometer = mSensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
// Get a reference to the magnetometer
magnetometer = mSensorManager
.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
// Exit unless both sensors are available
if (null == accelerometer || null == magnetometer)
finish();
}
@Override
protected void onResume() {
super.onResume();
// Register for sensor updates
mSensorManager.registerListener(this, accelerometer,
SensorManager.SENSOR_DELAY_NORMAL);
mSensorManager.registerListener(this, magnetometer,
SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
protected void onPause() {
super.onPause();
// Unregister all sensors
mSensorManager.unregisterListener(this);
}
@Override
public void onSensorChanged(SensorEvent event) {
// Acquire accelerometer event data
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
mGravity = new float[3];
System.arraycopy(event.values, 0, mGravity, 0, 3);
}
// Acquire magnetometer event data
else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
mGeomagnetic = new float[3];
System.arraycopy(event.values, 0, mGeomagnetic, 0, 3);
}
// If we have readings from both sensors then
// use the readings to compute the device's orientation
// and then update the display.
if (mGravity != null && mGeomagnetic != null) {
float rotationMatrix[] = new float[9];
// Users the accelerometer and magnetometer readings
// to compute the device's rotation with respect to
// a real world coordinate system
boolean success = SensorManager.getRotationMatrix(rotationMatrix,
null, mGravity, mGeomagnetic);
if (success) {
float orientationMatrix[] = new float[3];
// Returns the device's orientation given
// the rotationMatrix
SensorManager.getOrientation(rotationMatrix, orientationMatrix);
// Get the rotation, measured in radians, around the Z-axis
// Note: This assumes the device is held flat and parallel
// to the ground
float rotationInRadians = orientationMatrix[0];
// Convert from radians to degrees
mRotationInDegress = Math.toDegrees(rotationInRadians);
// Request redraw
mCompassArrow.invalidate();
// Reset sensor event data arrays
mGravity = mGeomagnetic = null;
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// N/A
}
public class CompassArrowView extends View {
Bitmap mBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.arrow);
int mBitmapWidth = mBitmap.getWidth();
// Height and Width of Main View
int mParentWidth;
int mParentHeight;
// Center of Main View
int mParentCenterX;
int mParentCenterY;
// Top left position of this View
int mViewTopX;
int mViewLeftY;
public CompassArrowView(Context context) {
super(context);
};
// Compute location of compass arrow
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mParentWidth = mFrame.getWidth();
mParentHeight = mFrame.getHeight();
mParentCenterX = mParentWidth / 2;
mParentCenterY = mParentHeight / 2;
mViewLeftY = mParentCenterX - mBitmapWidth / 2;
mViewTopX = mParentCenterY - mBitmapWidth / 2;
}
// Redraw the compass arrow
@Override
protected void onDraw(Canvas canvas) {
// Save the canvas
canvas.save();
// Rotate this View
canvas.rotate((float) -mRotationInDegress, mParentCenterX,
mParentCenterY);
// Redraw this View
canvas.drawBitmap(mBitmap, mViewLeftY, mViewTopX, null);
// Restore the canvas
canvas.restore();
}
}
}